package com.obrempon.module.easyhttp.callback;

import androidx.annotation.NonNull;


import com.obrempon.module.easyhttp.EasyLog;
import com.obrempon.module.easyhttp.EasyUtils;
import com.obrempon.module.easyhttp.config.IRequestInterceptor;
import com.obrempon.module.easyhttp.lifecycle.HttpLifecycleManager;
import com.obrempon.module.easyhttp.listener.OnHttpListener;
import com.obrempon.module.easyhttp.request.HttpRequest;

import java.io.InputStream;
import java.lang.reflect.Type;

import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 *    author : Android 轮子哥
 *    github : https://github.com/getActivity/EasyHttp
 *    time   : 2019/11/25
 *    desc   : 正常接口回调
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public final class NormalCallback extends BaseCallback {

    /** 请求配置 */
    private final HttpRequest mHttpRequest;
    /** 接口回调 */
    private OnHttpListener mListener;
    /** 解析类型 */
    private Type mReflectType;

    public NormalCallback(@NonNull HttpRequest request) {
        super(request);
        mHttpRequest = request;
    }

    public NormalCallback setListener(OnHttpListener listener) {
        mListener = listener;
        mReflectType = mHttpRequest.getRequestHandler().getGenericType(mListener);
        return this;
    }

    public NormalCallback setReflectType(Type reflectType) {
        mReflectType = reflectType;
        return this;
    }

    @Override
    public void start() {
        super.start();
    }

    @Override
    protected void onStart() {
        EasyUtils.runOnAssignThread(mHttpRequest.getThreadSchedulers(), this::dispatchHttpStartCallback);
    }

    @Override
    protected void onHttpResponse(Response response) throws Throwable {
        // 打印请求耗时时间
        EasyLog.printLog(mHttpRequest, "RequestConsuming：" +
                (response.receivedResponseAtMillis() - response.sentRequestAtMillis()) + " ms");

        IRequestInterceptor interceptor = mHttpRequest.getRequestInterceptor();
        if (interceptor != null) {
            response = interceptor.interceptResponse(mHttpRequest, response);
        }

        // 解析 Bean 类对象
        final Object result = mHttpRequest.getRequestHandler().requestSuccess(
                mHttpRequest, response, mReflectType);

        EasyUtils.runOnAssignThread(mHttpRequest.getThreadSchedulers(), () -> dispatchHttpSuccessCallback(result, false));
    }

    @Override
    protected void onHttpFailure(Throwable throwable) {
        // 打印错误堆栈
        EasyLog.printThrowable(mHttpRequest, throwable);
        final Throwable finalThrowable = mHttpRequest.getRequestHandler().requestFail(mHttpRequest, throwable);
        if (finalThrowable != throwable) {
            EasyLog.printThrowable(mHttpRequest, finalThrowable);
        }

        EasyUtils.runOnAssignThread(mHttpRequest.getThreadSchedulers(), () -> dispatchHttpFailCallback(finalThrowable));
    }

    private void dispatchHttpStartCallback() {
        if (mListener != null && HttpLifecycleManager.isLifecycleActive(mHttpRequest.getLifecycleOwner())) {
            mListener.onHttpStart(mHttpRequest.getRequestApi());
        }
        EasyLog.printLog(mHttpRequest,  "Http request start");
    }

    private void dispatchHttpSuccessCallback(@NonNull Object result, boolean cache) {
        if (mListener != null && HttpLifecycleManager.isLifecycleActive(mHttpRequest.getLifecycleOwner())) {
            mListener.onHttpSuccess(result, cache);
            mListener.onHttpEnd(mHttpRequest.getRequestApi());
        }
        EasyLog.printLog(mHttpRequest,  "Http request success");
    }

    private void dispatchHttpFailCallback(Throwable throwable) {
        if (mListener != null && HttpLifecycleManager.isLifecycleActive(mHttpRequest.getLifecycleOwner())) {
            mListener.onHttpFail(throwable);
            mListener.onHttpEnd(mHttpRequest.getRequestApi());
        }
        EasyLog.printLog(mHttpRequest,  "Http request fail");
    }

    @Override
    protected void closeResponse(Response response) {
        if (Response.class.equals(mReflectType) ||
                ResponseBody.class.equals(mReflectType) ||
                InputStream.class.equals(mReflectType)) {
            // 如果反射是这几个类型，则不关闭 Response，否则会导致拉取不到里面的流
            return;
        }
        super.closeResponse(response);
    }
}